export{}
/**
 * 装饰器
 */
function addNameEat(constructor:Function){
	constructor.prototype.name = 'jinyq'
	constructor.prototype.eat = function(){

	}
}
@addNameEat
class Person {
	name!:string;
	eat!: Function;
	constructor(){

	}
}
let p:Person = new Person()
console.log(p.name)
p.eat()

namespace b{
	function addNameFactory(name:string){
		return 	function addNameEat(constructor:Function){
			constructor.prototype.name = 'jinyq'
			constructor.prototype.eat = function(){
				console.log('eat')
			}
		}
	}
	@addNameFactory('jinyq')
	class Person {
		name!:string;
		eat!: Function;
		constructor(){
			
		}
	}
	let p:Person = new Person()
	console.log(p.name)
	p.eat()
}

//属性装饰器
/**
 * @param target 如果装饰的是实例属性的话，target是构造函数的原型
 * @param propertyKey
 */
namespace c{
	function upperCase(target:any, propertyKey:string){
		let value = target[propertyKey]
		const getter = () => value
		const setter = (newVal:string)=>{value = newVal.toUpperCase()}
		if(delete target[propertyKey]){
			Object.defineProperty(target,propertyKey,{
				get:getter,
				set: setter,
				enumerable: true,
				configurable: true
			})
		}
	}
	//静态属性装饰器
	/**
 * @param target 如果装饰的是实例属性的话，target是构造函数本身
 * @param propertyKey
 */
	function staticPropertyDecorator(target:any, propertyKey:string){

	}
	function noEnumerable(target:any, propertyKey:string, descriptor:PropertyDescriptor){
		console.log(target)
		descriptor.enumerable = false
	}
	function toNumber(target:any, propertyKey:string, descriptor:PropertyDescriptor){
		let oldMethod = descriptor.value;
		descriptor.value = function(...args:any[]){
			args = args.map(item=> parseFloat(item))
			return oldMethod.apply(this,args)
		}
	}
	class Person {
		@upperCase
		name:string = 'jinyq' //实例属性
		@staticPropertyDecorator
		public static age:number = 10; //静态属性
		constructor(){}
		@noEnumerable
		getName(){ //实例方法
			console.log(this.name)
		}
		@toNumber
		sum(...args:any[]){
			return args.reduce((accu:number, item: number)=> accu+item,0)
		}
	}

	let pn = new Person();
	console.log(pn.name)
}

//参数装饰器
namespace d {
	function addAge(targe:any,methodName: any,paramIndex:number){
		console.log(targe,methodName,paramIndex)
		targe.age =10

	}
	class Person{
		login(username:string,@addAge password:string){
			console.log(username, password)
		}
	}
	let p = new Person();
	p.login('jinyq','123')
}

//装饰器顺序
/**
 * 1.类装饰器最后执行的，厚些的类装饰器先执行
 * 2.方法和就去参数中的装饰器先执行参数
 * 3. 就去和属性装饰器，谁在前面先执行谁
 * 一般从内往外执行 先内后外
 *
 * 
 */
namespace e{
	function classDecorator1(){
		return function (target: any){
			console.log('classDecorator1')
		}
	}
	function classDecorator2(){
		return function (target: any){
			console.log('classDecorator2')
		}
	}
	function ProperDecortor(name:string){
		return function (target:any, propertyName:any){
			console.log('ProperDecortor',propertyName,name)
		}
	}
	function MethodDecortor(){
		return function (target:any, propertyName:any){
			console.log('MethodDecortor',propertyName)
		}
	}
	function ParameterDecortor(){
		return function (target:any, methodName:any,index:any){
			console.log('ParameterDecortor',methodName,index)
		}
	}
	@classDecorator1()
	@classDecorator2()
	class Person{
		@ProperDecortor('name')
		name:string= '';
		@ProperDecortor('age')
		age:number = 10;
		@MethodDecortor()
		hello(@ParameterDecortor() p1:string,@ParameterDecortor() p2:string){

		}
	}
}